// 文件：CertCreator.java
package net.yyge.apksigner.signer;

import net.yyge.apksigner.signer.utils.DistinguishedNameValues;
import net.yyge.apksigner.signer.utils.KeySet;
import net.yyge.apksigner.signer.utils.KeyStoreHelper;
import org.spongycastle.x509.X509V3CertificateGenerator;

import org.spongycastle.jce.X509Principal;
import java.io.File;
import java.io.IOException;
import java.math.BigInteger;
import java.security.*;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import java.util.Date;
import java.util.Random;

/**
 * 证书与密钥创建工具类。
 * 支持：
 * - 创建新的密钥库（JKS/BKS）并生成自签名密钥对
 * - 向现有密钥库中添加新密钥
 */
public class CertCreator {

    // 禁止实例化，模拟 Kotlin object 的单例行为
    private CertCreator() {
        throw new AssertionError("No instances.");
    }

    /**
     * 创建一个新的密钥库，并在其中生成一个自签名密钥。
     * 使用默认参数：RSA 2048, SHA1withRSA, 有效期 30 年，密钥密码与密钥库密码相同。
     *
     * @param keyFile                 新密钥库文件
     * @param password                密钥库和密钥的密码（char[]）
     * @param keyName                 密钥别名
     * @param distinguishedNameValues 证书主题信息（国家、组织、通用名等）
     * @return KeySet 包含私钥和公钥证书
     */
    public static KeySet createKeystoreAndKey(File keyFile, char[] password, String keyName,
                                              DistinguishedNameValues distinguishedNameValues) {
        return createKeystoreAndKey(
                keyFile, password,
                "RSA", 2048,
                keyName, password,
                "SHA1withRSA", 30,
                distinguishedNameValues
        );
    }

    /**
     * 创建一个新的密钥库，并在其中生成一个自签名密钥（可自定义参数）。
     *
     * @param keyFile                 新密钥库文件
     * @param storePass               密钥库密码
     * @param keyAlgorithm            密钥算法（如 RSA）
     * @param keySize                 密钥长度（如 2048）
     * @param keyName                 别名
     * @param keyPass                 密钥密码
     * @param certSignatureAlgorithm  证书签名算法（如 SHA1withRSA）
     * @param certValidityYears       证书有效期（年）
     * @param distinguishedNameValues 证书主题信息
     * @return KeySet 包含私钥和公钥证书
     * @throws RuntimeException 如果创建失败
     */
    public static KeySet createKeystoreAndKey(File keyFile, char[] storePass,
                                              String keyAlgorithm, int keySize,
                                              String keyName, char[] keyPass,
                                              String certSignatureAlgorithm, int certValidityYears,
                                              DistinguishedNameValues distinguishedNameValues) {
        try {
            // 检查文件是否已存在
            if (keyFile.exists()) {
                throw new IOException("File already exists: " + keyFile.getAbsolutePath());
            }

            // 生成密钥对和证书
            KeySet keySet = createKey(
                    keyAlgorithm, keySize, keyName,
                    certSignatureAlgorithm, certValidityYears,
                    distinguishedNameValues
            );

            // 创建空密钥库
            KeyStore privateKS = KeyStoreHelper.createKeyStore(keyFile, storePass);

            // 添加条目
            privateKS.setKeyEntry(keyName, keySet.getPrivateKey(), keyPass,
                    new Certificate[]{keySet.getPublicKey()});

            // 写入文件
            KeyStoreHelper.writeKeyStore(privateKS, keyFile, storePass);

            return keySet;

        } catch (RuntimeException e) {
            throw e;
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage(), e);
        }
    }

    /**
     * 向现有的密钥库中添加一个新的自签名密钥。
     *
     * @param keyFile                 现有或新建的密钥库文件
     * @param storePass               密钥库密码
     * @param keyAlgorithm            密钥算法
     * @param keySize                 密钥长度
     * @param keyName                 别名
     * @param keyPass                 密钥密码
     * @param certSignatureAlgorithm  证书签名算法
     * @param certValidityYears       证书有效期（年）
     * @param distinguishedNameValues 证书主题信息
     * @return KeySet 包含生成的私钥和公钥证书
     * @throws RuntimeException 如果操作失败
     */
    public static KeySet createKey(File keyFile, char[] storePass,
                                   String keyAlgorithm, int keySize,
                                   String keyName, char[] keyPass,
                                   String certSignatureAlgorithm, int certValidityYears,
                                   DistinguishedNameValues distinguishedNameValues) {
        try {
            // 生成密钥对和证书
            KeySet keySet = createKey(
                    keyAlgorithm, keySize, keyName,
                    certSignatureAlgorithm, certValidityYears,
                    distinguishedNameValues
            );

            // 加载或创建密钥库
            KeyStore privateKS = KeyStoreHelper.createKeyStore(keyFile, storePass);

            // 添加新条目
            privateKS.setKeyEntry(keyName, keySet.getPrivateKey(), keyPass,
                    new Certificate[]{keySet.getPublicKey()});

            // 写回文件
            KeyStoreHelper.writeKeyStore(privateKS, keyFile, storePass);

            return keySet;

        } catch (RuntimeException e) {
            throw e;
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage(), e);
        }
    }

    /**
     * 仅生成密钥对和自签名证书，不写入密钥库。
     *
     * @param keyAlgorithm            密钥算法（如 RSA）
     * @param keySize                 密钥长度（如 2048）
     * @param keyName                 别名（用于 KeySet 记录）
     * @param certSignatureAlgorithm  签名算法（如 SHA1withRSA）
     * @param certValidityYears       有效期（年）
     * @param distinguishedNameValues 主题信息
     * @return KeySet 包含私钥和 X.509 证书
     * @throws RuntimeException 如果生成失败
     */
    public static KeySet createKey(String keyAlgorithm, int keySize,
                                   String keyName, String certSignatureAlgorithm,
                                   int certValidityYears,
                                   DistinguishedNameValues distinguishedNameValues) {
        try {
            // 生成密钥对
            KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(keyAlgorithm);
            keyPairGenerator.initialize(keySize);
            KeyPair keyPair = keyPairGenerator.generateKeyPair();

            // 创建证书生成器
            X509V3CertificateGenerator v3CertGen = new X509V3CertificateGenerator();
            X509Principal principal = distinguishedNameValues.getPrincipal(); // 假设 getPrincipal() 返回 X509Name 或类似类型

            // 生成正数序列号
            BigInteger serialNumber;
            do {
                serialNumber = BigInteger.valueOf(new Random().nextInt());
            } while (serialNumber.compareTo(BigInteger.ZERO) <= 0);

            v3CertGen.setSerialNumber(serialNumber);
            v3CertGen.setIssuerDN(principal);
            v3CertGen.setSubjectDN(principal);
            v3CertGen.setNotBefore(new Date(System.currentTimeMillis() - 1000L * 60L * 60L * 24L * 30L)); // 30 天前
            v3CertGen.setNotAfter(new Date(System.currentTimeMillis() + 1000L * 60L * 60L * 24L * 366L * certValidityYears)); // N 年后
            v3CertGen.setPublicKey(keyPair.getPublic());
            v3CertGen.setSignatureAlgorithm(certSignatureAlgorithm);

            // 生成证书（使用私钥签名）
            X509Certificate certificate = v3CertGen.generate(keyPair.getPrivate());

            // 封装结果
            KeySet keySet = new KeySet();
            keySet.setName(keyName);
            keySet.setPrivateKey(keyPair.getPrivate());
            keySet.setPublicKey(certificate);

            return keySet;

        } catch (Exception e) {
            throw new RuntimeException(e.getMessage(), e);
        }
    }
}